import {
  Button,
  Card,
  Checkbox,
  Col,
  DatePicker,
  Form,
  Input,
  Popover,
  Row,
  Select,
  Tooltip,
  TreeSelect,
  message,
} from 'antd'
import React, { useCallback, useRef, useState } from 'react'
import moment from 'moment'
import { useAntdTable, useLocalStorageState, useRequest } from 'ahooks'
import groupBy from 'lodash/groupBy'
import ProcessRunModal from '../ProcessManager/ProcessRun/ProcessRunModal'
import ProcessStatus from './ProcessStatus'
import BatchReRunModal from './BatchReRunModal'
import request from '@/utils/request'
import { GlobalFormLayout } from '@/layouts/Form'
import Space from '@/components/Space'
import SlickTable from '@/components/SlickTable'
import useProcessCatalogTree from '@/hooks/UseProcessCatalogTree'
import Status from '@/components/Status'
import useModal from '@/hooks/UseModal'

export const DATASOURCE_ID_HEADER = 'X-TG-DatasourceId'

const { RangePicker } = DatePicker
const defaultColumns = [
  'processName',
  'processCode',
  'instanceId',
  'extension',
  'mockSituation',
  'startTime',
  'errorCode',
  'errorDesc',
  'status',
  'operation',
]

export function getTableData({ current, pageSize, datasourceId, ...rest }) {
  return request.post('/processLog/page', {
    data: {
      current,
      pageSize,
      ...rest,
    },
    headers: {
      [DATASOURCE_ID_HEADER]: datasourceId,
    },
  })
}

function ProcessLogQuery({ form, goToStep }) {
  const { getFieldDecorator, getFieldsValue, resetFields, setFieldsValue, getFieldValue } = form
  const [showColumns, setShowColumns] = useLocalStorageState('tangram-filter-columns', {
    defaultValue: defaultColumns,
  })

  const [flag, setFlag] = useState(false)

  const [enableWildcardInstanceId, setEnableWildcardInstanceId] = useState(false)

  const firstRef = useRef(true)
  const [selectedRows, setSelectedRows] = useState([])
  const { showModal, hideModal, visible, data: modalData } = useModal()

  const { data = [] } = useRequest(() => request.get('/dynamicDatasource/list'))

  const {
    tableProps: { pagination, ...restTableProps },
  } = useAntdTable(
    (query) => {
      const fieldsValue = getFieldsValue()
      const data = {
        ...fieldsValue,
        minStartTime: fieldsValue.startTimeRange[0].format('YYYY-MM-DD HH:mm:ss'),
        maxStartTime: fieldsValue.startTimeRange[1].format('YYYY-MM-DD HH:mm:ss'),
        processCode:
          fieldsValue.processCode || (fieldsValue.processCode2 ? [fieldsValue.processCode2] : []),
        enableWildcardInstanceId,
      }
      if (firstRef.current) {
        firstRef.current = false
        return Promise.resolve({ list: [], total: 0 })
      }
      return getTableData({ ...query, ...data })
    },
    {
      defaultPageSize: 10,
      refreshDeps: [flag],
    },
  )

  const refresh = () => {
    setFlag(!flag)
  }

  const columns = [
    {
      title: '流程日志ID',
      dataIndex: 'processLogId',
    },
    {
      title: '流程名称',
      dataIndex: 'processName',
    },
    {
      title: '流程编码',
      dataIndex: 'processCode',
    },
    {
      title: '流程生效版本号',
      dataIndex: 'processVersionNumber',
    },
    {
      title: '事务ID',
      dataIndex: 'transactionId',
    },
    {
      title: '实例ID',
      dataIndex: 'instanceId',
    },
    {
      title: '轨迹ID',
      dataIndex: 'traceId',
    },
    {
      title: '扩展信息',
      dataIndex: 'extension',
    },
    {
      title: '客户端IP',
      dataIndex: 'clientIp',
    },
    {
      title: '服务端IP',
      dataIndex: 'serverIp',
    },

    {
      title: '开始时间',
      dataIndex: 'startTime',
    },
    {
      title: '结束时间',
      dataIndex: 'endTime',
    },
    {
      title: '流程耗时',
      dataIndex: 'duration',
      render: milliseconds => (milliseconds ? `${milliseconds} ms` : ''),
    },
    {
      title: '异常编码',
      dataIndex: 'errorCode',
    },
    {
      title: '异常描述信息',
      dataIndex: 'errorDesc',
    },
    {
      title: 'mock情况',
      dataIndex: 'mockSituation',
      render(text) {
        switch (text) {
          case 0:
            return <Status type="success">无mock</Status>
          case 1:
            return <Status type="warning">部分mock</Status>
          case 2:
            return <Status type="info">全部mock</Status>
          default:
            return null
        }
      },
    },
    {
      title: '执行状态',
      dataIndex: 'status',
      render: status => <ProcessStatus status={status} />,
    },
    {
      title: '分片键',
      dataIndex: 'shardingKey',
    },
    {
      title: '操作',
      dataIndex: 'operation',
      render: (_text, record) => {
        const { processId, processVersionId, processLogId, shardingKey } = record
        return (
          <Space divider="vertical">
            <a onClick={() => goToStep(2, { record, datasourceId: getFieldsValue().datasourceId })}>日志详情</a>
            <ProcessRunModal
              title="流程重演"
              processLogId={record.processLogId}
              processId={processId}
              versionId={processVersionId}
              shardingKey={shardingKey}
              initContentLoader={() =>
                request.get(
                  `/processLog/getRequestContent?processLogId=${processLogId}&shardingKey=${shardingKey
                  || ''}`,
                  {
                    headers: {
                      [DATASOURCE_ID_HEADER]: getFieldsValue().datasourceId,
                    },
                  },
                )
              }
            >
              <a>流程重演</a>
            </ProcessRunModal>
          </Space>
        )
      },
    },
  ]

  const disableTreeNode = useCallback((node) => {
    return !node.leaf
  }, [])

  const { renderTree, loading: treeLoading } = useProcessCatalogTree({ disableTreeNode })

  /**
   * 过滤函数
   */
  const filter = useCallback((inputValue, treeNode) => {
    const data = treeNode.props.dataRef
    if (!data.leaf)
      return false

    const processName = data.title.toLowerCase()
    const processCode = data.processCode.toLowerCase()
    const input = inputValue.toLowerCase()
    return processCode.includes(input) || processName.includes(input)
  }, [])

  /**
   * 筛选列弹窗
   */
  const popoverContent = (
    <div>
      <Checkbox.Group
        value={showColumns}
        style={{ width: '100%' }}
        onChange={setShowColumns}
      >
        {columns.map(item => (
          <Row key={item.dataIndex} style={{ marginBottom: '5px' }}>
            <Col span={24}>
              <Checkbox value={item.dataIndex}>{item.title}</Checkbox>
            </Col>
          </Row>
        ))}
      </Checkbox.Group>
      <a onClick={() => setShowColumns(defaultColumns)}>恢复默认</a>
    </div>
  )

  /**
   * 列过滤函数
   */
  const filterColumns = useCallback(
    (columns) => {
      return columns.filter(column => showColumns.includes(column.dataIndex))
    },
    [showColumns],
  )

  return (
    <Card className="cute" bodyStyle={{ padding: '32px' }} title="流程日志查询">
      <Form {...GlobalFormLayout} style={{ marginBottom: '16px' }}>
        <Row gutter={16}>
          <Col span={8} style={{ height: 32 }}>
            <Form.Item label="流程">
              {getFieldDecorator('processCode')(
                <TreeSelect
                  onChange={(v) => {
                    if (v) {
                      setFieldsValue({
                        processCode2: undefined,
                      })
                    }
                  }}
                  multiple
                  showSearch
                  placeholder="--请选择--"
                  loading={treeLoading}
                  filterTreeNode={filter}
                  allowClear
                >
                  {renderTree()}
                </TreeSelect>,
              )}
            </Form.Item>
          </Col>
          {/* <Col span={8}>
            <Form.Item label="流程名称">
              {getFieldDecorator('processName')(
                <Input onPressEnter={refresh} placeholder="请输入" />
              )}
            </Form.Item>
          </Col> */}
          <Col span={8}>
            <Form.Item label="流程编码">
              {getFieldDecorator('processCode2')(
                <Input
                  onChange={(e) => {
                    if (e.target.value) {
                      setFieldsValue({
                        processCode: undefined,
                      })
                    }
                  }}
                  onPressEnter={refresh}
                  placeholder="请输入"
                />,
              )}
            </Form.Item>
          </Col>

          <Col span={8}>
            <Form.Item label="开始时间">
              {getFieldDecorator('startTimeRange', {
                initialValue: [
                  moment()
                    .startOf('day')
                    .subtract(2, 'weeks'),
                  moment().endOf('day'),
                ],
              })(
                <RangePicker
                  allowClear={false}
                  onPressEnter={refresh}
                  showTime={{ format: 'HH:mm:ss' }}
                  style={{ width: '100%' }}
                />,
              )}
            </Form.Item>
          </Col>
          <Col span={8} style={{ height: 32 }}>
            <Form.Item label="实例ID">
              {getFieldDecorator('instanceId')(
                <Input
                  onPressEnter={refresh}
                  placeholder="请输入"
                  addonAfter={
                    <Tooltip title="开启模糊匹配 ( like '%xxx%' ) ">
                      <Checkbox
                        checked={enableWildcardInstanceId}
                        onChange={(e) => {
                          setEnableWildcardInstanceId(e.target.checked)
                        }}
                      />
                    </Tooltip>
                  }
                />,
              )}
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label="轨迹ID">
              {getFieldDecorator('traceId')(<Input onPressEnter={refresh} placeholder="请输入" />)}
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label="流程生效版本号">
              {getFieldDecorator('processVersionNumber')(
                <Input onPressEnter={refresh} placeholder="请输入" />,
              )}
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label="扩展信息">
              {getFieldDecorator('extension')(
                <Input onPressEnter={refresh} placeholder="请输入" />,
              )}
            </Form.Item>
          </Col>
          <Col span={8} style={{ height: 32 }}>
            <Form.Item label="执行状态">
              {getFieldDecorator('status')(
                <Select mode="multiple" placeholder="--请选择--" allowClear>
                  {[0, 1, 2, 3, 4].map(status => (
                    <Select.Option value={status} key={status}>
                      <ProcessStatus status={status} />
                    </Select.Option>
                  ))}
                </Select>,
              )}
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label="异常编码">
              {getFieldDecorator('errorCode')(<Input placeholder="请输入" />)}
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label="事务ID">
              {getFieldDecorator('transactionId')(
                <Input onPressEnter={refresh} placeholder="请输入" />,
              )}
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label="分片键">
              {getFieldDecorator('shardingKey')(
                <Input onPressEnter={refresh} placeholder="请输入" />,
              )}
            </Form.Item>
          </Col>
          {data.length > 0 && <Col span={8}>
            <Form.Item label="数据源">
              {getFieldDecorator('datasourceId')(
                <Select placeholder="默认数据源">
                  {data.map(item => (
                    <Select.Option key={item} value={item}>
                      {item}
                    </Select.Option>
                  ))}
                </Select>,
              )}
            </Form.Item>
          </Col>
          }

        </Row>
        <Row className="margin-top" gutter={16} type="flex" justify="center">
          <Space>
            <Popover placement="bottom" content={popoverContent}>
              <Button style={{ marginRight: '10px' }} icon="unordered-list">
                筛选
              </Button>
            </Popover>
            <Button type="primary" onClick={refresh}>
              查询
            </Button>
            <Button type="default" onClick={() => resetFields()}>
              重置
            </Button>
          </Space>
        </Row>
      </Form>
      <SlickTable
        pick="checkbox"
        onSelectRow={setSelectedRows}
        selectedRows={selectedRows}
        rowKey="processLogId"
        columns={filterColumns(columns)}
        data={{ pagination }}
        extra={
          selectedRows.length
            ? (
              <Button onClick={() => {
                const groups = groupBy(selectedRows, row => row.processCode)
                const processCodes = Object.keys(groups)
                if (processCodes.length > 1) {
                  message.warning({
                    content: (
                      <>
                        <span>只有流程编码相同的日志，才能进行批量重演</span>
                        <div>当前选中的流程包括：</div>
                        {processCodes.map(code => <div>{code}</div>)}
                      </>
                    ),
                    duration: 4,
                  })
                  return
                }
                showModal({ selectedRows })
              }}>
                批量重演
              </Button>
              )
            : null
        }
        {...restTableProps}
      />
      <BatchReRunModal isOpen={visible} onCancel={hideModal} data={modalData} />
    </Card>
  )
}

export default Form.create()(ProcessLogQuery)
